#include "ServerInfo.h"

#include <core/FileSys.h>
#include <core/sharedata/login_data.h>
#include <qbtools/aess.h>

#include <QDomDocument>
#include <QFile>
#include <QSettings>
#include <algorithm>

static const char* s_key = "www.sumscope.com";

QuoteServerInfo& QuoteServerInfo::instance() {
  static QuoteServerInfo s_qsi;
  return s_qsi;
}

ServerInfo QuoteServerInfo::currentServer() {
  ServerInfo si;
  bool found = false;
  for (auto g : m_serverGroups) {
    if (g.index == m_currentGroup) {
      for (auto server : g.servers) {
        if (server.index == m_currentServer) {
          si = server;
          found = true;
          break;
        }
      }
      break;
    }
  }
  if (!found && !m_serverGroups.empty() && !m_serverGroups[0].servers.empty())
    return m_serverGroups[0].servers[0];

  return si;
}

void QuoteServerInfo::updateUserInfo(const LoginUserInfo& v) {
  m_loginUserInfo = v;
  saveConfig();
}

void QuoteServerInfo::updateProxyInfo(const ProxyInfo& v) {
  m_proxyInfo = v;
  //	m_proxyInfo.bUse = m_proxyInfo.nProxyType > kProxyBrowser;
  saveConfig();
}

QuoteServerInfo::QuoteServerInfo() { loadConfig(); }

void QuoteServerInfo::loadConfig() {
  // server
  QFile file(FileSys::instance()->appCfgDir() + "/ServerConfig.xml");
  while (true) {
    if (!file.open(QFile::ReadOnly)) break;
    QDomDocument doc;
    if (!doc.setContent(&file)) {
      file.close();
      return;
    }
    file.close();
    QDomElement root = doc.documentElement();
    QDomNodeList nodeList = root.childNodes();
    for (int i = 0; i < nodeList.count(); ++i) {
      QDomElement node = nodeList.at(i).toElement();
      ServerGroup group;
      group.index = node.attribute("Index", "0").toInt();
      group.name = node.attribute("Name", "").toStdWString();
      group.en_name = node.attribute("EnName", "").toStdString();

      QDomNodeList serverList = node.childNodes();
      for (int j = 0; j < serverList.count(); ++j) {
        QDomElement server = serverList.at(j).toElement();
        ServerInfo si;
        si.index = server.attribute("Index", "0").toInt();
        QDomElement address = server.firstChildElement("Address");
        if (!address.isNull()) si.address = address.text().toStdString();

        QDomElement port = server.firstChildElement("Port");
        if (!port.isNull()) si.port = port.text().toInt();

        if (!si.address.empty() && si.port > 0) group.servers.push_back(si);
      }

      std::sort(group.servers.begin(), group.servers.end(),
                [](const ServerInfo& l, const ServerInfo& r) {
                  return l.index < r.index;
                });
      m_serverGroups.push_back(group);
    }
    std::sort(m_serverGroups.begin(), m_serverGroups.end(),
              [](const ServerGroup& l, const ServerGroup& r) {
                return l.index < r.index;
              });

    break;
  }
  // user
  QSettings settings(
      FileSys::instance()->writeableAppCfgDir() + "/QuoteServer.ini",
      QSettings::IniFormat);
  settings.beginGroup("User");
  m_loginUserInfo.strUser = settings.value("Name", "").toString().toStdString();
  m_loginUserInfo.lastServerGroupIndex =
      settings.value("ServerGroup", 0).toInt();
  m_loginUserInfo.autoRun = settings.value("AutoLogin", "false").toBool();
  m_loginUserInfo.savePwd = settings.value("SavePasswd", "false").toBool();
  if (m_loginUserInfo.savePwd) {
    m_loginUserInfo.strPwd =
        settings.value("Passwd", "").toString().toStdString();
    m_loginUserInfo.strPwd = decryptPwd(m_loginUserInfo.strPwd);
  }

  settings.endGroup();

  settings.beginGroup("Proxy");
  m_proxyInfo.nProxyType = (ProxyType)settings.value("ProxyType", "0").toInt();
  m_proxyInfo.bUse = settings.value("ProxybUse", "false").toBool();
  //	m_proxyInfo.bUse = m_proxyInfo.nProxyType > ProxyType::kProxyBrowser;
  //	if (m_proxyInfo.bUse)
  //	{
  m_proxyInfo.strProxyHost =
      settings.value("ProxyAddress", "").toString().toStdString();
  m_proxyInfo.nProxyPort = settings.value("ProxyPort", "").toInt();
  m_proxyInfo.strUsername =
      settings.value("ProxyUser", "").toString().toStdString();
  m_proxyInfo.strPassword =
      settings.value("ProxyPasswd", "").toString().toStdString();
  if (m_proxyInfo.strPassword != "") {
    m_proxyInfo.strPassword = decryptPwd(m_proxyInfo.strPassword);
  }
  //	}
  settings.endGroup();

  qb::LoginProxyInfo loginProxyInfo;
  loginProxyInfo.strProxyHost = m_proxyInfo.strProxyHost;
  loginProxyInfo.strUsername = m_proxyInfo.strUsername;
  loginProxyInfo.strPassword = m_proxyInfo.strPassword;
  loginProxyInfo.strDomain = m_proxyInfo.strDomain;
  loginProxyInfo.nProxyPort = m_proxyInfo.nProxyPort;
  loginProxyInfo.nProxyType = (qb::LoginProxyType)m_proxyInfo.nProxyType;
  loginProxyInfo.bUse = m_proxyInfo.bUse;
  qb::loginData::instance().SetProxyInfo(loginProxyInfo);
}

void QuoteServerInfo::saveConfig() {
  QSettings settings(
      FileSys::instance()->writeableAppCfgDir() + "/QuoteServer.ini",
      QSettings::IniFormat);
  settings.beginGroup("User");
  settings.setValue("Name", QString::fromStdString(m_loginUserInfo.strUser));
  if (m_loginUserInfo.savePwd)
    settings.setValue("Passwd", encryptPwd(m_loginUserInfo.strPwd));
  settings.setValue("ServerGroup", m_loginUserInfo.lastServerGroupIndex);
  settings.setValue("AutoLogin", m_loginUserInfo.autoRun);
  settings.setValue("SavePasswd", m_loginUserInfo.savePwd);
  settings.endGroup();

  settings.beginGroup("Proxy");
  settings.setValue("ProxybUse", m_proxyInfo.bUse);
  settings.setValue("ProxyType", m_proxyInfo.nProxyType);
  settings.setValue("ProxyAddress",
                    QString::fromStdString(m_proxyInfo.strProxyHost));
  settings.setValue("ProxyPort", m_proxyInfo.nProxyPort);
  settings.setValue("ProxyUser",
                    QString::fromStdString(m_proxyInfo.strUsername));
  settings.setValue("ProxyPasswd", encryptPwd(m_proxyInfo.strPassword));
  settings.endGroup();

  qb::LoginProxyInfo loginProxyInfo;
  loginProxyInfo.strProxyHost = m_proxyInfo.strProxyHost;
  loginProxyInfo.strUsername = m_proxyInfo.strUsername;
  loginProxyInfo.strPassword = m_proxyInfo.strPassword;
  loginProxyInfo.strDomain = m_proxyInfo.strDomain;
  loginProxyInfo.nProxyPort = m_proxyInfo.nProxyPort;
  loginProxyInfo.nProxyType = (qb::LoginProxyType)m_proxyInfo.nProxyType;
  loginProxyInfo.bUse = m_proxyInfo.bUse;
  qb::loginData::instance().SetProxyInfo(loginProxyInfo);
}

QString QuoteServerInfo::encryptPwd(const std::string& str) {
  char* buffer = new char[2048];
  memset(buffer, 0, 2048);

  AES aes(s_key);
  int size = aes.DataEncrypt(str.c_str(), s_key, buffer, "");
  QString res;
  for (int i = 0; i < size; ++i) {
    res += QString("%1").arg((uchar)buffer[i], 2, 16, QChar('0'));
  }

  delete[] buffer;
  return res;
}

std::string QuoteServerInfo::decryptPwd(const std::string& str) {
  char* pszData = new char[2048];
  memset(pszData, 0, 2048);

  char ch[3] = {0};
  int nLen = str.length();
#ifndef _MSC_VER
  char* pszAsc = strdup(str.c_str());
#else
  char* pszAsc = _strdup(str.c_str());
#endif

  for (int i = 0; i < (nLen / 2); i++) {
    memcpy(ch, &pszAsc[i * 2], sizeof(char) * 2);
    if ((ch[0] >= '0') && (ch[0] <= '9'))
      pszData[i] = ch[0] - 0x30;
    else if ((ch[0] >= 'A') && (ch[0] <= 'F'))
      pszData[i] = ch[0] - 'A' + 10;
    else if ((ch[0] >= 'a') && (ch[0] <= 'f'))
      pszData[i] = ch[0] - 'a' + 10;
    else
      Q_ASSERT(0);

    pszData[i] *= 16;
    if ((ch[1] >= '0') && (ch[1] <= '9'))
      pszData[i] += ch[1] - 0x30;
    else if ((ch[1] >= 'A') && (ch[1] <= 'F'))
      pszData[i] += ch[1] - 'A' + 10;
    else if ((ch[1] >= 'a') && (ch[1] <= 'f'))
      pszData[i] += ch[1] - 'a' + 10;
    else
      Q_ASSERT(0);
  }
  if (pszAsc) free(pszAsc);

  AES aes(s_key);
  char* pszDecrypt = (char*)malloc(2000);
  memset(pszDecrypt, 0, sizeof(char) * 2000);
  std::string res;
  if (aes.DataDecrypt(pszData, s_key, pszDecrypt, "", (uint32_t)nLen / 2)) {
    res = pszDecrypt;
  }

  delete[] pszData;
  free(pszDecrypt);
  return res;
}

void QuoteServerInfo::savepwd(std::string strpassword) {
  m_loginUserInfo.strPwd = strpassword;
  // user
  QSettings settings(
      FileSys::instance()->writeableAppCfgDir() + "/QuoteServer.ini",
      QSettings::IniFormat);
  settings.beginGroup("User");
  if (m_loginUserInfo.savePwd)
    settings.setValue("Passwd", encryptPwd(m_loginUserInfo.strPwd));
  settings.endGroup();
}
